﻿/*MyPhotoIndex Free Photo Organizer <www.myphotoindex.com>
  Copyright (C) <2006-2009>  <Asaf Yarkoni asaf@yarkoni.net>

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Security.Cryptography;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace MyPhotoIndex.Plugins.WebHost.Security
{
    public class Authentication
    {
        private static readonly string AUTHENTICATION_COOKIE_NAME = "mpiAuth";
        private static string m_privetKey = "02E6C748-5B2B-41b3-98CC-7212B0BE12C6";

        public static bool IsAuthenticated(HttpListenerRequest request)
        {
            Cookie authCookie = request.Cookies[AUTHENTICATION_COOKIE_NAME];
            if (authCookie == null || 
                string.IsNullOrEmpty(authCookie.Value) == true)
            {
                return false;
            }

            AuthCookieValue authCookieValue = null;
            byte[] cookieValue = Decript(authCookie.Value, m_privetKey);
            using (MemoryStream ms = new MemoryStream(cookieValue))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                authCookieValue = formatter.Deserialize(ms) as AuthCookieValue;
            }

            if (string.IsNullOrEmpty(authCookieValue.UserName) == false &&
                string.Compare(authCookieValue.UserName, WebHostPluginSettings.Default.UserName) == 0)
            {
                return true;
            }

            return false;
        }

        public static bool Authenticate(HttpListenerResponse response, string userName, string password)
        {
            string authCookieString = string.Empty;

            //consider adding real user management
            string storedUserName = WebHostPluginSettings.Default.UserName;
            string storedPassword = WebHostPluginSettings.Default.Password;

            if (string.Compare(userName, storedUserName, true) == 0 &&
                string.Compare(password, storedPassword, false) == 0)
            {
                AuthCookieValue authCookieValue = new AuthCookieValue();
                authCookieValue.UserName = userName;

                BinaryFormatter formatter = new BinaryFormatter();
                using (MemoryStream ms = new MemoryStream())
                {
                    formatter.Serialize(ms, authCookieValue);
                    ms.Position = 0;
                    authCookieString = Encript(ms.ToArray(), m_privetKey);
                }
            }

            response.Cookies.Add(new Cookie(AUTHENTICATION_COOKIE_NAME, authCookieString));
            return (string.IsNullOrEmpty(authCookieString) == false);
        }

        private static byte[] Decript(string value, string key)
        {
            byte[] shaShortKey = ComputeKey(key);

            TripleDESCryptoServiceProvider encryptionProvider = new TripleDESCryptoServiceProvider();
            using (ICryptoTransform transform = encryptionProvider.CreateDecryptor(shaShortKey, shaShortKey))
            {
                byte[] tempData = Convert.FromBase64String(value);
                byte[] enccryptedData = transform.TransformFinalBlock(tempData, 0, tempData.Length);
                return enccryptedData;
            }
        }

        private static string Encript(byte[] value, string key)
        {
            byte[] shaShortKey = ComputeKey(key);

            TripleDESCryptoServiceProvider encryptionProvider = new TripleDESCryptoServiceProvider();
            using (ICryptoTransform transform = encryptionProvider.CreateEncryptor(shaShortKey, shaShortKey))
            {
                byte[] enccryptedData = transform.TransformFinalBlock(value, 0, value.Length);
                string base64 = Convert.ToBase64String(enccryptedData);
                return base64;
            }
        }

        static byte[] ComputeKey(string key)
        {
            SHA512Managed sha = new SHA512Managed();

            byte[] hashKey = ASCIIEncoding.ASCII.GetBytes(key);
            byte[] shaKey = sha.ComputeHash(hashKey);
            byte[] shaShortKey = new byte[24];
            for (int ii = 0; ii < 24; ii++) shaShortKey[ii] = shaKey[ii];

            return shaShortKey;
        }
    }
}
